package com.ruoyi.common.utils.ps;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*; 
import java.util.regex.Pattern;

/**
 * 多层图片文件夹处理器（支持去重和Prompt文本提取）
 */
public class ImageFolderProcessor {

    // 静态配置参数
    public static final String SOURCE_FOLDER_PATH = "D:\\BaiduNetdiskDownload\\ps30W供应商数据\\0923\\耐特-9.23"; // 源文件夹路径
    public static final String OUTPUT_EXCEL_PATH = SOURCE_FOLDER_PATH + "\\"; // 输出Excel目录
    public static final String[] IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"}; // 支持的图片格式
    public static final String TEXT_EXTENSION = ".txt"; // 文本文件扩展名
    public static final String PROMPT_SUFFIX = "-prompt"; // Prompt文件后缀

    // 日志与日期格式化
    private static final Logger logger = LogManager.getLogger(ImageFolderProcessor.class);
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 主方法：程序入口
     */
    public static void main(String[] args) {
        logger.info("=== 开始处理图片文件夹 ===");

        try {
            processImageFolderAndGenerateExcel();
            logger.info("=== 处理完成，Excel文件已生成 ===");
        } catch (Exception e) {
            logger.error("处理过程中发生错误", e);
        }
    }

    /**
     * 获取源文件夹最后一层名称（用于Excel文件名和工作表名）
     */
    public static String getLastFolderName() {
        Path sourcePath = Paths.get(SOURCE_FOLDER_PATH);
        return sourcePath.getNameCount() > 0 ?
                sourcePath.getFileName().toString() : "ImageReport";
    }

    /**
     * 获取完整输出Excel路径（格式：[文件夹名]_[日期].xlsx）
     */
    public static String getOutputExcelFullPath() {
        String fileName = String.format("%s_%s.xlsx",
                getLastFolderName(),
                LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        return OUTPUT_EXCEL_PATH + fileName;
    }

    /**
     * 核心逻辑：处理文件夹并生成Excel
     */
    public static void processImageFolderAndGenerateExcel() throws IOException {
        // 创建Excel工作簿和工作表
        try (Workbook workbook = new XSSFWorkbook()) {
            String sheetName = getLastFolderName();
            if (sheetName.length() > 31) sheetName = sheetName.substring(0, 31); // Excel工作表名最长31字符
            Sheet sheet = workbook.createSheet(sheetName);

            // 创建表头（含新增的"Prompt"列）
            createHeaderRow(sheet);

            // 遍历文件夹并收集数据（去重后）
            Set<ImageData> imageDataSet = traverseFolderAndCollectData();
            List<ImageData> imageDataList = new ArrayList<>(imageDataSet);

            // 填充数据到Excel
            fillDataRows(sheet, imageDataList);

            // 自动调整列宽
            autoResizeColumns(sheet);

            // 写入文件
            writeWorkbookToFile(workbook, getOutputExcelFullPath());
        }
    }

    /**
     * 创建Excel表头（含"Prompt"列）
     */
    private static void createHeaderRow(Sheet sheet) {
        Row headerRow = sheet.createRow(0);
        String[] headers = {
                "供应商名称", "当前日期", "一级分类", "二级分类",
                "原图名称", "原图名称2", "处理图名称1",
                "处理图名称2", "处理图名称3", "处理图名称4", "Prompt" // 新增Prompt列
        };

        CellStyle headerStyle = createHeaderStyle(sheet.getWorkbook());
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }
    }

    /**
     * 创建表头样式（加粗、灰色背景、边框）
     */
    private static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 12);
        style.setFont(font);
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }

    /**
     * 遍历文件夹并收集图片数据（使用LinkedHashSet去重并保留顺序）
     */
    public static Set<ImageData> traverseFolderAndCollectData() throws IOException {
        Set<ImageData> imageDataSet = new LinkedHashSet<>();
        Path sourcePath = Paths.get(SOURCE_FOLDER_PATH);

        if (!Files.exists(sourcePath)) {
            logger.error("源文件夹不存在: {}", SOURCE_FOLDER_PATH);
            return imageDataSet;
        }
        if (!Files.isDirectory(sourcePath)) {
            logger.error("源路径不是文件夹: {}", SOURCE_FOLDER_PATH);
            return imageDataSet;
        }

        logger.info("开始遍历文件夹: {}", SOURCE_FOLDER_PATH);

        // 遍历所有文件，处理原始图片（不含"-"的图片文件）
        Files.walk(sourcePath)
                .filter(Files::isRegularFile)
                .forEach(filePath -> {
                    try {
                        String fileName = filePath.getFileName().toString();
                        if (isOriginalImageFile(fileName) && !fileName.contains("-")) {
                            processImageFile(filePath, imageDataSet);
                        }
                    } catch (Exception e) {
                        logger.warn("处理文件失败: {}", filePath, e);
                    }
                });

        return imageDataSet;
    }

    /**
     * 处理单个图片文件，提取分类、原图组合、Prompt内容并添加到数据集
     */
    private static void processImageFile(Path filePath, Set<ImageData> imageDataSet) {
        Path directory = filePath.getParent();
        if (directory.getNameCount() < 3) { // 确保目录层级足够（至少3层：供应商/一级分类/二级分类）
            logger.debug("目录层级不足，跳过文件: {}", filePath);
            return;
        }

        // 提取目录信息（供应商、一级分类、二级分类）
        String secondaryCategory = directory.getFileName().toString();
        String primaryCategory = directory.getParent().getFileName().toString();
        String supplierName = directory.getParent().getParent().getFileName().toString();
        String originalFileName = getFileNameWithoutExtension(filePath.getFileName().toString());

        File directoryFile = directory.toFile();
        File[] allFiles = directoryFile.listFiles();
        if (allFiles == null) return;

        ImageData imageData = new ImageData();
        imageData.setSupplierName(supplierName);
        imageData.setPrimaryCategory(primaryCategory);
        imageData.setSecondaryCategory(secondaryCategory);
        imageData.setOriginalImageName(originalFileName);

        // 查找处理图、第二个原图、Prompt内容
        findRelatedProcessedImages(originalFileName, allFiles, imageData);
        findSecondOriginalImage(originalFileName, allFiles, imageData);
        imageData.setPromptText(readPromptFileContent(originalFileName, allFiles)); // 新增：读取Prompt内容

        // 统一多图组合顺序（A+B和B+A视为同一组合）
        if (imageData.getSecondOriginalImageName() != null) {
            String img1 = imageData.getOriginalImageName();
            String img2 = imageData.getSecondOriginalImageName();
            if (img2 != null && !img2.isEmpty() && img1.compareTo(img2) > 0) {
                imageData.setOriginalImageName(img2);
                imageData.setSecondOriginalImageName(img1);
            }
        }

        imageDataSet.add(imageData);
    }

    /**
     * 查找与原图相关的处理图（如A-1.jpg, A-2.jpg）
     */
    private static void findRelatedProcessedImages(String originalFileName, File[] allFiles, ImageData imageData) {
        List<String> processedImageNames = new ArrayList<>();
        for (File file : allFiles) {
            String fileName = file.getName();
            if (isProcessedImageFile(fileName, originalFileName)) {
                processedImageNames.add(getFileNameWithoutExtension(fileName));
            }
        }

        // 按数字编号排序处理图（如A-1, A-2）
        processedImageNames.sort(Comparator.comparingInt(ImageFolderProcessor::extractNumberFromProcessedImage));

        // 最多保留4个处理图
        for (int i = 0; i < Math.min(4, processedImageNames.size()); i++) {
            imageData.setProcessedImageName(i, processedImageNames.get(i));
        }
    }

    /**
     * 查找第二个原图（从多图Prompt文件中提取，如A-B-prompt.txt中的B）
     */
    private static void findSecondOriginalImage(String originalFileName, File[] allFiles, ImageData imageData) {
        for (File file : allFiles) {
            String fileName = file.getName();
            if (fileName.contains(originalFileName) && fileName.contains(PROMPT_SUFFIX) && fileName.endsWith(TEXT_EXTENSION)) {
                String[] parts = fileName.split("-");
                if (parts.length >= 3 && parts[parts.length - 1].equals("prompt.txt")) {
                    if (parts[0].equals(originalFileName)) {
                        imageData.setSecondOriginalImageName(parts[1]);
                    } else if (parts[1].equals(originalFileName)) {
                        imageData.setSecondOriginalImageName(parts[0]);
                    }
                    logger.debug("找到多图组合: {} + {}", originalFileName, imageData.getSecondOriginalImageName());
                    break;
                }
            }
        }
    }

    /**
     * 读取Prompt文件内容（从A-prompt.txt或A-B-prompt.txt中读取）
     */
    private static String readPromptFileContent(String originalFileName, File[] allFiles) {
        for (File file : allFiles) {
            String fileName = file.getName();
            if (fileName.contains(originalFileName) && fileName.contains(PROMPT_SUFFIX) && fileName.endsWith(TEXT_EXTENSION)) {
                try {
                    List<String> lines = Files.readAllLines(file.toPath());
                    return String.join("\n", lines).trim(); // 保留换行符
                } catch (IOException e) {
                    logger.warn("读取Prompt文件失败: {}", file.getAbsolutePath(), e);
                    return "";
                }
            }
        }
        return ""; // 无Prompt文件时返回空
    }

    /**
     * 填充数据到Excel行
     */
    private static void fillDataRows(Sheet sheet, List<ImageData> imageDataList) {
        int rowNum = 1;
        String currentDate = LocalDate.now().format(DATE_FORMATTER);
        CellStyle dataStyle = createDataStyle(sheet.getWorkbook());

        for (ImageData data : imageDataList) {
            Row row = sheet.createRow(rowNum++);

            // 填充基础信息（10列）
            setCellValueWithStyle(row, 0, data.getSupplierName(), dataStyle);
            setCellValueWithStyle(row, 1, currentDate, dataStyle);
            setCellValueWithStyle(row, 2, data.getPrimaryCategory(), dataStyle);
            setCellValueWithStyle(row, 3, data.getSecondaryCategory(), dataStyle);
            setCellValueWithStyle(row, 4, data.getOriginalImageName(), dataStyle);
            setCellValueWithStyle(row, 5, data.getSecondOriginalImageName() != null ? data.getSecondOriginalImageName() : "", dataStyle);

            // 填充处理图名称（4列）
            for (int i = 0; i < 4; i++) {
                String processedName = data.getProcessedImageName(i);
                setCellValueWithStyle(row, 6 + i, processedName != null ? processedName : "", dataStyle);
            }

            // 填充Prompt内容（新增列）
            setCellValueWithStyle(row, 10, data.getPromptText(), dataStyle);
        }
        logger.info("已填充 {} 行数据到Excel", imageDataList.size());
    }

    /**
     * 设置单元格值并应用样式
     */
    private static void setCellValueWithStyle(Row row, int columnIndex, String value, CellStyle style) {
        Cell cell = row.createCell(columnIndex);
        cell.setCellValue(value);
        cell.setCellStyle(style);
    }

    /**
     * 创建数据行样式（边框）
     */
    private static CellStyle createDataStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }

    /**
     * 自动调整Excel列宽
     */
    private static void autoResizeColumns(Sheet sheet) {
        for (int i = 0; i < 11; i++) { // 共11列（含Prompt列）
            sheet.autoSizeColumn(i);
        }
    }

    /**
     * 将Excel工作簿写入文件
     */
    private static void writeWorkbookToFile(Workbook workbook, String filePath) throws IOException {
        Path outputDir = Paths.get(filePath).getParent();
        if (outputDir != null && !Files.exists(outputDir)) {
            Files.createDirectories(outputDir);
        }

        try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
            workbook.write(outputStream);
        }
    }

    /**
     * 判断是否为原始图片文件（不含"-"且为支持的图片格式）
     */
    private static boolean isOriginalImageFile(String fileName) {
        for (String ext : IMAGE_EXTENSIONS) {
            if (fileName.toLowerCase().endsWith(ext) && !fileName.contains("-")) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否为处理后的图片文件（含原图名称和数字编号，如A-1.jpg）
     */
    private static boolean isProcessedImageFile(String fileName, String originalFileName) {
        // 检查扩展名是否为图片
        boolean isImage = Arrays.stream(IMAGE_EXTENSIONS)
                .anyMatch(ext -> fileName.toLowerCase().endsWith(ext));
        if (!isImage) return false;

        // 检查是否包含原图名称和数字编号（如A-1.jpg）
        return fileName.contains(originalFileName) &&
                fileName.contains("-") &&
                Pattern.compile(".*-\\d+\\..*").matcher(fileName).matches();
    }

    /**
     * 从处理图名称中提取数字编号（如A-2.jpg提取2）
     */
    private static int extractNumberFromProcessedImage(String fileName) {
        try {
            int lastDashIndex = fileName.lastIndexOf("-");
            if (lastDashIndex != -1) {
                String numberStr = fileName.substring(lastDashIndex + 1);
                return Integer.parseInt(numberStr);
            }
        } catch (NumberFormatException e) {
            logger.debug("无法提取处理图编号: {}", fileName);
        }
        return 0;
    }

    /**
     * 获取不带扩展名的文件名
     */
    private static String getFileNameWithoutExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf('.');
        return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
    }

    /**
     * 图片数据模型类（存储供应商、分类、原图组合、处理图、Prompt等信息）
     */
    static class ImageData {
        private String supplierName;
        private String primaryCategory;
        private String secondaryCategory;
        private String originalImageName;
        private String secondOriginalImageName;
        private final String[] processedImageNames = new String[4]; // 最多4个处理图
        private String promptText; // 新增：Prompt文本内容

        // Getter和Setter
        public String getSupplierName() { return supplierName; }
        public void setSupplierName(String supplierName) { this.supplierName = supplierName; }

        public String getPrimaryCategory() { return primaryCategory; }
        public void setPrimaryCategory(String primaryCategory) { this.primaryCategory = primaryCategory; }

        public String getSecondaryCategory() { return secondaryCategory; }
        public void setSecondaryCategory(String secondaryCategory) { this.secondaryCategory = secondaryCategory; }

        public String getOriginalImageName() { return originalImageName; }
        public void setOriginalImageName(String originalImageName) { this.originalImageName = originalImageName; }

        public String getSecondOriginalImageName() { return secondOriginalImageName; }
        public void setSecondOriginalImageName(String secondOriginalImageName) { this.secondOriginalImageName = secondOriginalImageName; }

        public String getProcessedImageName(int index) {
            return (index >= 0 && index < 4) ? processedImageNames[index] : null;
        }
        public void setProcessedImageName(int index, String name) {
            if (index >= 0 && index < 4) processedImageNames[index] = name;
        }

        public String getPromptText() { return promptText; } // 新增：获取Prompt内容
        public void setPromptText(String promptText) { this.promptText = promptText; } // 新增：设置Prompt内容

        // 去重逻辑：基于供应商、分类、原图组合（单图/多图）
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ImageData other = (ImageData) o;

            // 核心字段：供应商、一级分类、二级分类必须相同
            if (!Objects.equals(supplierName, other.supplierName)) return false;
            if (!Objects.equals(primaryCategory, other.primaryCategory)) return false;
            if (!Objects.equals(secondaryCategory, other.secondaryCategory)) return false;

            // 单图/多图判断
            boolean isThisMulti = secondOriginalImageName != null && !secondOriginalImageName.isEmpty();
            boolean isOtherMulti = other.secondOriginalImageName != null && !other.secondOriginalImageName.isEmpty();

            // 单图 vs 单图：原图名称必须相同
            if (!isThisMulti && !isOtherMulti) {
                return Objects.equals(originalImageName, other.originalImageName);
            }

            // 多图 vs 多图：原图组合（A+B和B+A视为相同）
            if (isThisMulti && isOtherMulti) {
                boolean sameOrder = Objects.equals(originalImageName, other.originalImageName) &&
                        Objects.equals(secondOriginalImageName, other.secondOriginalImageName);
                boolean reverseOrder = Objects.equals(originalImageName, other.secondOriginalImageName) &&
                        Objects.equals(secondOriginalImageName, other.originalImageName);
                return sameOrder || reverseOrder;
            }

            // 单图 vs 多图：不同
            return false;
        }

        @Override
        public int hashCode() {
            int baseHash = Objects.hash(supplierName, primaryCategory, secondaryCategory);
            if (secondOriginalImageName == null || secondOriginalImageName.isEmpty()) {
                return Objects.hash(baseHash, originalImageName); // 单图哈希
            } else {
                // 多图哈希（排序后确保A+B和B+A哈希相同）
                String img1 = originalImageName;
                String img2 = secondOriginalImageName;
                if (img1.compareTo(img2) > 0) {
                    String temp = img1;
                    img1 = img2;
                    img2 = temp;
                }
                return Objects.hash(baseHash, img1, img2);
            }
        }
    }
}